﻿namespace Harness.Commands
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    internal class DialogCommand : ICommand
    {
        #region Constants

        private const int DialogTypeArgIndex = 0;

        private const int AlertScreenshotArgIndex = 2;

        private const int ConfirmAnswerArgIndex = 1;
        private const int ConfirmScreenshotArgIndex = 2;

        private const int PromptAnswerArgIndex = 1;
        private const int PromptValueArgIndex = 2;
        private const int PromptScreenshotArgIndex = 3;

        private const int AuthIdArgIndex = 1;
        private const int AuthPasswordArgIndex = 2;
        private const int AuthScreenshotArgIndex = 3;

        private const int FileSelectPathArgIndex = 1;
        private const int FileSelectScreenshotArgIndex = 2;

        private const int FileDownloadAnswerArgIndex = 1;
        private const int FileDownloadScreenshotArgIndex = 2;

        #endregion

        #region Public Methods

        public void SyntaxCheck(IHarness harness, IEnumerable<object> args)
        {
            if (null == args.ElementAtOrDefault(DialogTypeArgIndex))
            {
                throw new ArgumentNullException((DialogTypeArgIndex + 1).ToString() + ":DialogType");
            }
        }

        public dynamic Execute(IHarness harness, IEnumerable<object> args)
        {
            string dialogType = (args.ElementAtOrDefault(DialogTypeArgIndex) ?? string.Empty).ToString().ToLower();

            switch (dialogType)
            {
                case "alert":
                    this.Alert(args);
                    break;

                case "confirm":
                    this.Confirm(args);
                    break;

                case "prompt":
                    this.Prompt(args);
                    break;

                case "fileselect":
                case "file":
                    this.FileSelect(args);
                    break;

                case "filedownload":
                case "download":
                    this.FileDownload(args);
                    break;

                case "auth":
                case "authentication":
                case "login":
                    this.Authentication(args);
                    break;

                case "error":
                case "scripterror":
                    this.ScriptError(args);
                    break;

                default:
                    string msg = string.Format(Properties.Resources.Exception_UnknownDialogType, dialogType);
                    throw new ArgumentException(msg);
            }

            return null;
        }

        #endregion

        #region Private Methods

        private void Alert(IEnumerable<object> args)
        {
            string filename = args.ElementAtOrDefault(AlertScreenshotArgIndex) as string;
            IE.Dialog.AlertClose(filename);
        }

        private void Confirm(IEnumerable<object> args)
        {
            string answer = (args.ElementAtOrDefault(ConfirmAnswerArgIndex) ?? "ok").ToString().ToLower();
            string screenshot = args.ElementAtOrDefault(ConfirmScreenshotArgIndex) as string;

            switch (answer)
            {
                case "ok":
                case "accept":
                    IE.Dialog.ConfirmOk(screenshot);
                    break;

                default:
                    IE.Dialog.ConfirmCancel(screenshot);
                    break;
            }
        }

        private void Prompt(IEnumerable<object> args)
        {
            string answer = (args.ElementAtOrDefault(PromptAnswerArgIndex) ?? "ok").ToString().ToLower();
            string value = (args.ElementAtOrDefault(PromptValueArgIndex) ?? string.Empty).ToString();
            string screenshot = args.ElementAtOrDefault(PromptScreenshotArgIndex) as string;

            switch (answer)
            {
                case "ok":
                case "accept":
                    IE.Dialog.PromptOk(value, screenshot);
                    break;

                default:
                    IE.Dialog.PromptCancel(screenshot);
                    break;
            }
        }

        private void Authentication(IEnumerable<object> args)
        {
            string id = (args.ElementAtOrDefault(AuthIdArgIndex) ?? string.Empty).ToString();

            if (string.IsNullOrWhiteSpace(id))
            {
                throw new ArgumentNullException((AuthIdArgIndex + 1).ToString() + ":UserID");
            }

            string password = (args.ElementAtOrDefault(AuthPasswordArgIndex) ?? string.Empty).ToString();

            if (string.IsNullOrWhiteSpace(password))
            {
                throw new ArgumentNullException((AuthPasswordArgIndex + 1).ToString() + ":Password");
            }

            string screenshot = args.ElementAtOrDefault(AuthScreenshotArgIndex) as string;

            IE.Dialog.LoginOnNextAuthentication(id, password, screenshot);
        }

        private void FileDownload(IEnumerable<object> args)
        {
            string answer = (args.ElementAtOrDefault(FileDownloadAnswerArgIndex) ?? "ok").ToString().ToLower();
            string screenshot = args.ElementAtOrDefault(FileDownloadScreenshotArgIndex) as string;

            switch (answer)
            {
                case "ok":
                case "save":
                    IE.Dialog.FileDownloadSave(screenshot);
                    break;

                default:
                    IE.Dialog.FileDownloadCancel(screenshot);
                    break;
            }
        }

        private void FileSelect(IEnumerable<object> args)
        {
            string path = (args.ElementAtOrDefault(FileSelectPathArgIndex) ?? string.Empty).ToString();

            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException((FileSelectPathArgIndex + 1).ToString() + ":Path");
            }

            string screenshot = args.ElementAtOrDefault(FileSelectScreenshotArgIndex) as string;

            IE.Dialog.FileSelect(path, screenshot);
        }

        private void ScriptError(IEnumerable<object> args)
        {
            IE.Dialog.AutoCloseScriptError();
        }

        #endregion
    }
}
